package util

import (
	"fmt"
	"io"
	"os"
	"regexp"
	"sort"
	"strings"
	"unicode"
)

// GetModuleName 从当前工作目录下的go.mod文件中提取模块名称。
// 返回模块名称和可能出现的错误。
// GetModuleName 获取go.mod文件里的module名称
func GetModuleName() (string, error) {
	dir, err := os.Getwd()
	if err != nil {
		return "", err
	}
	file, err := os.Open(dir + "/go.mod")
	if err != nil {
		return "", err
	}
	defer file.Close()

	data, err := io.ReadAll(file)
	if err != nil {
		return "", err
	}

	re := regexp.MustCompile(`(?m)module\s+(.*)`)
	res := re.FindSubmatch(data)
	moduleName := ""
	if res != nil || len(res) != 2 {
		moduleName = string(res[1])
	}
	if moduleName == "" {
		return "", fmt.Errorf("从go.mod文件提取module失败")
	}

	return moduleName, nil
}

// InStringArr 检查一个字符串是否存在于字符串数组中。
// arr: 字符串数组，待检查的数组。
// str: 待检查的字符串。
// 返回值: 如果 str 存在于 arr 中，则返回 true；否则返回 false。
func InStringArr(arr []string, str string) bool {
	for _, v := range arr {
		if v == str {
			return true
		}
	}
	return false
}

type ByString []string

func (s ByString) Len() int {
	return len(s)
}
func (s ByString) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}
func (s ByString) Less(i, j int) bool {
	return s[i] < s[j] // 这里定义了升序排序，根据需要可以改为s[i] > s[j]实现降序
}

// SortStrings 对字符串数组进行排序。
// 它接受一个字符串切片作为输入，并通过定义的排序规则对其进行排序。
// 排序是通过嵌套的ByString类型实现的，该类型实现了sort.Interface接口的三个方法，
// 从而允许sort包中的排序算法对字符串切片进行排序。
func SortStrings(arr []string) {
	sort.Sort(ByString(arr))
}

// ToUpperFirst 首字母大写
func ToUpperFirst(s string) string {
	if len(s) == 0 {
		return s
	}

	// 将第一个字符转换为大写，其余字符保持不变
	return string(unicode.ToUpper(rune(s[0]))) + s[1:]
}

// ToLowerFirst 首字母小写
func ToLowerFirst(s string) string {
	if len(s) == 0 {
		return s
	}

	// 将第一个字符转换为小写，其余字符保持不变
	return string(unicode.ToLower(rune(s[0]))) + s[1:]
}

// GetImportAsName 获取pb的import别名
func GetImportAsName(goPackage, goModule string) string {
	importAsStr := strings.ReplaceAll(goPackage, goModule, "")
	importAsStr = strings.ReplaceAll(importAsStr, "-", "/")
	importAsStr = strings.ReplaceAll(importAsStr, "_", "/")
	importAsStr = strings.TrimLeft(importAsStr, "/")
	importAsArr := strings.Split(importAsStr, "/")
	for i, v := range importAsArr {
		if v == "" {
			continue
		}
		if i == 0 {
			importAsArr[i] = ToLowerFirst(v)
		} else {
			importAsArr[i] = ToUpperFirst(v)
		}
	}
	importAsStr = strings.Join(importAsArr, "")
	return importAsStr
}

// PascalToSnake 将大驼峰字符串转换为下划线格式
func PascalToSnake(s string) string {
	// 使用正则表达式匹配大写字母前的位置
	re := regexp.MustCompile(`([a-z0-9])([A-Z])`)
	// 在大写字母前添加下划线
	snake := re.ReplaceAllString(s, `${1}_${2}`)
	// 转换为小写
	return strings.ToLower(snake)
}
